Horizontal alignment reporter
Description
Remarks
Source Code
//Required References
using System;
using System.Collections.Generic;
using Bentley.DgnPlatformNET;
using Bentley.CifNET.GeometryModel.SDK;
using Bentley.CifNET.SDK;
using Bentley.CifNET.LinearGeometry;
using Bentley.CifNET.Formatting;
namespace ManagedSDKExample.Examples
{
class HorizontalAlignmentReporter
{
internal static DgnModel m_activeModel = Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModel();
internal static int LinearPrecision { get { return GetDesignFilePrecision(); } }
// Report Options | Run on all alignments in active model
/*--------------+---------------+---------------+---------------+---------------+------*/
public void ReportAllAlignments()
{
ConsensusConnection sdkCon = Bentley.CifNET.SDK.Edit.ConsensusConnectionEdit.GetActive();
if (sdkCon == null)
return;
GeometricModel geomModel = sdkCon.GetActiveGeometricModel();
if (geomModel == null)
return;
// Cycle through Horizontal Alignments
foreach (Alignment al in geomModel.Alignments)
{
if (!al.IsFinalElement)
continue;
ReportAlignment(al);
}
}
// Report Options | Run on given alignment
/*--------------+---------------+---------------+---------------+---------------+------*/
public void ReportSingleAlignment(Alignment al)
{
ReportAlignment(al);
}
// Utility Function | Read and display data for given alignment
/*--------------+---------------+---------------+---------------+---------------+------*/
internal void ReportAlignment(Alignment al)
{
// Generate Alignment Header
string name = "Unnamed", style = "";
if (al.Name != null && al.Name != "")
name = al.Name;
if (al.FeatureName != null)
style = al.FeatureName;
// Report Elements in Alignment
LinearElement[] elements = { };
try
{
LinearComplex alComplex = (LinearComplex)al.LinearGeometry;
elements = alComplex.GetSubLinearElements();
}
catch
{
elements = new LinearElement[1];
elements[0] = al.LinearGeometry;
}
AlignmentPropertyReader propReader = new AlignmentPropertyReader(al);
foreach (LinearElement le in elements)
{
Dictionary<string, string> elementProperties = propReader.Read(le);
}
}
// Report Options | Run on all alignments in active model
/*--------------+---------------+---------------+---------------+---------------+------*/
public void ReportAllAlignmentsItemTypes()
{
ConsensusConnection sdkCon = Bentley.CifNET.SDK.Edit.ConsensusConnectionEdit.GetActive();
if (sdkCon == null)
return;
GeometricModel geomModel = sdkCon.GetActiveGeometricModel();
if (geomModel == null)
return;
List<string> labels = new List<string>() { "Item Type Library Name", "Item Type Name", "Property Name", "Property Type", "Property Value" };
DgnModel dgn = geomModel.DgnModel;
DgnFile file = dgn.GetDgnFile();
Dictionary<string, string> fileProperties = new Dictionary<string, string>();
fileProperties.Add("Project", dgn.ModelName);
fileProperties.Add("File Name", file.GetFileName());
fileProperties.Add("Last Accessed", file.LastSaveTimeUtc.ToString());
// Cycle through Horizontal Alignments
foreach (Alignment al in geomModel.Alignments)
{
if (!al.IsFinalElement)
continue;
// Generate Alignment Header
string name = string.IsNullOrEmpty(al.Name) ? "Unnamed" : al.Name;
string style = string.IsNullOrEmpty(al.FeatureName) ? "No Feature Definition" : al.FeatureName;
CustomItemHost host = new CustomItemHost(al.Element, true);
if (host != null && host.CustomItemsCount > 0)
{
List<string> data = new List<string>();
foreach (Bentley.DgnPlatformNET.DgnEC.IDgnECInstance instance in host.CustomItems)
{
data.Add(string.Format("{0}|{1}|||", instance.ClassDefinition.Schema.NamespacePrefix, instance.ClassDefinition.Name));
foreach (Bentley.ECObjects.Instance.IECPropertyValue propertyValue in instance)
{
string propertyType = propertyValue.Type.DisplayLabel;
string value = "";
if (propertyValue is Bentley.ECObjects.Instance.IECArrayValue)
{
Bentley.ECObjects.Instance.IECArrayValue ecArray = propertyValue as Bentley.ECObjects.Instance.IECArrayValue;
foreach (Bentley.ECObjects.Instance.IECPropertyValue arrayValue in ecArray.ContainedValues)
{
if (arrayValue.ArrayIndex == 0)
{
propertyType = "Array<" + arrayValue.Type.DisplayLabel + ">";
}
value += GetFormattedPropertyValue(arrayValue);
if (arrayValue.ArrayIndex < ecArray.Count - 1)
{
value += "<br />";
}
}
}
else
{
value = GetFormattedPropertyValue(propertyValue);
}
data.Add(string.Format("||{0}|{1}|{2}", propertyValue.AccessString, propertyType, value));
}
}
}
}
}
// Utility Class | Reads properties from linear elements for horizontal alignments.
/*--------------+---------------+---------------+---------------+---------------+------*/
internal class AlignmentPropertyReader
{
private Alignment m_alignment;
private StationingFormatter sFormatter;
public AlignmentPropertyReader(Alignment al)
{
m_alignment = al;
sFormatter = new StationingFormatter(m_alignment);
}
// Generic read function determines element type and passes to specific read function
public Dictionary<string, string> Read(LinearElement le)
{
Dictionary<string, string> properties = new Dictionary<string, string>();
if (le is Line)
properties = ReadLine(le as Line);
else if (le is Spiral)
properties = ReadSpiral(le as Spiral);
else if (le is CircularArc)
properties = ReadCircularArc(le as CircularArc);
if (properties.Count == 0)
properties.Add("No properties read for element", le.GetType().Name);
return properties;
}
// Reads Bentley.CifNET.LinearGeometry.Line
internal Dictionary<string, string> ReadLine(Line line)
{
Dictionary<string, string> lineProperties = new Dictionary<string, string>();
lineProperties.Add("Element", line.GetType().Name);
lineProperties.Add("Start", GetStation(m_alignment, line.StartPoint.Coordinates) + " | " + FormatCoordinates(line.StartPoint));
lineProperties.Add("End", GetStation(m_alignment, line.EndPoint.Coordinates) + " | " + FormatCoordinates(line.EndPoint));
lineProperties.Add("Tangential Direction", FormatDirection(line.Direction));
lineProperties.Add("Tangential Length", FormatDistance(line.Length));
return lineProperties;
}
// Reads Bentley.CifNET.LinearGeometry.Spiral
internal Dictionary<string, string> ReadSpiral(Spiral spiral)
{
Dictionary<string, string> spiralProperties = new Dictionary<string, string>();
spiralProperties.Add("Element", spiral.SpiralType.ToString());
spiralProperties.Add("Start", GetStation(m_alignment, spiral.StartPoint.Coordinates) + " | " + FormatCoordinates(spiral.StartPoint));
Bentley.GeometryNET.DPoint3d pi = GetPI(spiral);
spiralProperties.Add("SPI", GetStation(m_alignment, pi) + " | " + FormatCoordinates(pi));
spiralProperties.Add("End", GetStation(m_alignment, spiral.EndPoint.Coordinates) + " | " + FormatCoordinates(spiral.EndPoint));
spiralProperties.Add("Entrance Radius", FormatDistance(Math.Abs(spiral.StartRadius)));
spiralProperties.Add("Exit Radius", FormatDistance(Math.Abs(spiral.EndRadius)));
spiralProperties.Add("Length", FormatDistance(spiral.Length));
spiralProperties.Add("Angle", FormatAngleDirection(spiral.SweepAngle));
spiralProperties.Add("Constant", FormatNumber(spiral.Constant));
spiralProperties.Add("Long Tangent", FormatDistance(spiral.LongTangent));
spiralProperties.Add("Short Tangent", FormatDistance(spiral.ShortTangent));
spiralProperties.Add("Long Chord", FormatDistance(spiral.LongChord));
spiralProperties.Add("Xs", FormatNumber(spiral.Xs));
spiralProperties.Add("Ys", FormatNumber(spiral.Ys));
spiralProperties.Add("P", FormatNumber(spiral.PValue));
spiralProperties.Add("K", FormatNumber(spiral.KValue));
spiralProperties.Add("Tangent Direction (Start)", FormatDirection(spiral.StartPoint.TangentDirection));
spiralProperties.Add("Radial Direction (Start)", GetRadialDirection(spiral.StartPoint));
spiralProperties.Add("Chord Direction", GetChordDirection(spiral.StartPoint, spiral.EndPoint));
spiralProperties.Add("Radial Direction (End)", GetRadialDirection(spiral.EndPoint));
spiralProperties.Add("Tangent Direction (End)", FormatDirection(spiral.EndPoint.TangentDirection));
return spiralProperties;
}
// Reads Bentley.CifNET.LinearGeometry.CircularArc
internal Dictionary<string, string> ReadCircularArc(CircularArc arc)
{
Dictionary<string, string> arcProperties = new Dictionary<string, string>();
arcProperties.Add("Element", arc.GetType().Name);
arcProperties.Add("Start", GetStation(m_alignment, arc.StartPoint.Coordinates) + " | " + FormatCoordinates(arc.StartPoint));
Bentley.GeometryNET.DPoint3d pi = GetPI(arc);
arcProperties.Add("PI", Get_PI_Station(m_alignment, arc) + " | " + FormatCoordinates(pi));
arcProperties.Add("CC", " | " + FormatCoordinates(arc.CenterPoint));
arcProperties.Add("End", GetStation(m_alignment, arc.EndPoint.Coordinates) + " | " + FormatCoordinates(arc.EndPoint));
arcProperties.Add("Radius", FormatDistance(Math.Abs(arc.Radius)));
arcProperties.Add("Delta", FormatAngleDirection(arc.SweepAngle));
arcProperties.Add("Degree of Curvature (Arc)", FormatDegreeOfCurve(arc.Radius));
arcProperties.Add("Length", FormatDistance(arc.Length));
arcProperties.Add("Tangent", FormatDistance(arc.TangentDistance));
arcProperties.Add("Chord", FormatDistance(arc.ChordDistance));
double delta = Math.Abs(arc.SweepAngle);
arcProperties.Add("Middle Ordinate", FormatDistance((delta >= Math.PI) ? 0.0 : (Math.Abs(arc.Radius) * (1.0 - Math.Cos(0.5 * delta)))));
arcProperties.Add("External", FormatDistance((delta > Math.PI) ? 0.0 : (Math.Abs(arc.TangentDistance) * Math.Tan(0.25 * delta))));
arcProperties.Add("Tangent Direction (Start)", FormatDirection(arc.StartPoint.TangentDirection));
arcProperties.Add("Radial Direction (Start)", GetRadialDirection(arc.StartPoint));
arcProperties.Add("Chord Direction", GetChordDirection(arc.StartPoint, arc.EndPoint));
arcProperties.Add("Radial Direction (End)", GetRadialDirection(arc.EndPoint));
arcProperties.Add("Tangent Direction (End)", FormatDirection(arc.EndPoint.TangentDirection));
return arcProperties;
}
}
private string GetFormattedPropertyValue(Bentley.ECObjects.Instance.IECPropertyValue property)
{
if (Bentley.ECObjects.ECObjects.BooleanType == property.Type ||
Bentley.ECObjects.ECObjects.IntegerType == property.Type ||
Bentley.ECObjects.ECObjects.StringType == property.Type)
{
return property.StringValue;
}
else if (Bentley.ECObjects.ECObjects.DateTimeType == property.Type)
{
DateTime? dateTime = property.NativeValue as DateTime?;
if (dateTime.HasValue)
{
return dateTime.ToString();
}
}
else if (Bentley.ECObjects.ECObjects.DoubleType == property.Type)
{
return FormatNumber(property.DoubleValue);
}
else if (Bentley.ECObjects.ECObjects.PointType == property.Type)
{
Bentley.GeometryNET.DPoint3d? point = property.NativeValue as Bentley.GeometryNET.DPoint3d?;
if (point.HasValue)
{
return "[" + FormatNumber(point.Value.X) + ", " + FormatNumber(point.Value.Y) + "]";
}
}
return string.Empty;
}
private static string GetStation(Alignment al, Bentley.GeometryNET.DPoint3d point)
{
LinearPoint stationPoint = al.LinearGeometry.ProjectPointOnPerpendicular(point);
// Get numerical station
string stationStr = "";
double stationNum = stationPoint.DistanceOnExtension + stationPoint.DistanceAlong;
// Format it
StationingFormatter sformatter = new StationingFormatter(al);
StationFormatSettings settings = StationFormatSettings.GetStationFormatSettingsForModel(m_activeModel);
sformatter.FormatStation(ref stationStr, stationNum, settings);
return stationStr;
}
public static string FormatCoordinates(LinearPoint point)
{
string y = FormatForDisplay.Coordinate(point.Coordinates.Y, m_activeModel);
string y2 = FormatForDisplay.Coordinate(point.Coordinates.Y);
string x = FormatForDisplay.Coordinate(point.Coordinates.X, m_activeModel);
return "( " + y + ", " + x + " )";
}
public static string FormatCoordinates(Bentley.GeometryNET.DPoint3d point)
{
string y = FormatForDisplay.Coordinate(point.Y, m_activeModel);
string x = FormatForDisplay.Coordinate(point.X, m_activeModel);
return "( " + y + ", " + x + " )";
}
public static string FormatDirection(double value)
{
ModelInfo info = m_activeModel.GetModelInfo();
return FormatForDisplay.Direction(value, m_activeModel);
}
public static string FormatDistance(double value)
{
return FormatForDisplay.Distance(value, m_activeModel, LinearPrecision);
}
public static string FormatNumber(double num)
{
return FormatForDisplay.Double(num);
}
/*------------------------------------------------------------------------------------**/
/* Alignment property calculations
/*--------------+---------------+---------------+---------------+---------------+------*/
public static Bentley.GeometryNET.DPoint3d GetPI(LinearElement le)
{
double x = 0.0, y = 0.0;
if (le is Spiral)
{
Spiral spiral = le as Spiral;
if (spiral.IsOutgoing)
{
x = spiral.StartPoint.Coordinates.X + spiral.ShortTangent * Math.Cos(spiral.StartDirection);
y = spiral.StartPoint.Coordinates.Y + spiral.ShortTangent * Math.Sin(spiral.StartDirection);
}
else
{
x = spiral.StartPoint.Coordinates.X + spiral.LongTangent * Math.Cos(spiral.StartDirection);
y = spiral.StartPoint.Coordinates.Y + spiral.LongTangent * Math.Sin(spiral.StartDirection);
}
}
else if (le is CircularArc)
{
CircularArc arc = le as CircularArc;
Bentley.GeometryNET.DPoint3d point;
arc.PIPoint(out point);
return point;
}
return new Bentley.GeometryNET.DPoint3d(x, y);
}
public static string FormatAngleDirection(double valueRadians)
{
string direction = (valueRadians > 0) ? "Left" : "Right";
ModelInfo info = m_activeModel.GetModelInfo();
string angle= FormatForDisplay.Angle(Math.Abs(valueRadians), m_activeModel);
return angle + " " + direction;
}
public static string GetRadialDirection(LinearPoint point)
{
double direction = (point.TangentDirection - (Math.PI * 0.5)) % (2.0 * Math.PI);
if (direction < 0)
direction = (Math.PI * 2.0) + direction;
return FormatDirection(direction);
}
public static string GetChordDirection(LinearPoint p1, LinearPoint p2)
{
double azimuth = 0.0;
if (p1.Coordinates.X == p2.Coordinates.X)
azimuth = (p2.Coordinates.Y >= p1.Coordinates.Y) ? 0.0 : Math.PI;
double stagedValue = Math.Atan2(p2.Coordinates.X - p1.Coordinates.X, p2.Coordinates.Y - p1.Coordinates.Y);
if (p2.Coordinates.X > p1.Coordinates.X)
azimuth = stagedValue;
else
azimuth = stagedValue + 2.0 * Math.PI;
double dDir = 0.5 * Math.PI - azimuth;
return FormatDirection(dDir);
}
internal static string Get_PI_Station(Alignment al, CircularArc arc)
{
// Get numerical station
string stationStr = "";
LinearPoint startPoint = al.LinearGeometry.ProjectPointOnPerpendicular(arc.StartPoint.Coordinates);
double stationNum = startPoint.DistanceOnExtension + startPoint.DistanceAlong + arc.TangentDistance;
// Format it
StationingFormatter sformatter = new StationingFormatter(al);
StationFormatSettings settings = StationFormatSettings.GetStationFormatSettingsForModel(m_activeModel);
sformatter.FormatStation(ref stationStr, stationNum, settings);
return stationStr;
}
internal static int GetDesignFilePrecision()
{
int precision = 0;
// Get the precision out of the PrecisionFormat enum
PrecisionFormat lp = m_activeModel.GetModelInfo().LinearPrecision;
string[] splitPrec = lp.ToString().Split('_');
if (splitPrec.Length >= 2)
int.TryParse(splitPrec[1], out precision);
if (precision > 0)
return precision;
else
return 3; // Default is 3
}
public static string FormatDegreeOfCurve(double radius)
{
ModelInfo info = m_activeModel.GetModelInfo();
double radiusInMasterUnits = radius / (info.UorPerMaster / info.UorPerMeter);
double valueRadians = 100.0 / (radiusInMasterUnits);
return FormatForDisplay.Angle(valueRadians, m_activeModel);
}
}
}